package leetcode1116;

import java.util.concurrent.Semaphore;
import java.util.function.IntConsumer;

/**
 * 1116. 打印零与奇偶数
 * 相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程：
 * <p>
 * 线程 A 将调用 zero()，它只输出 0 。
 * 线程 B 将调用 even()，它只输出偶数。
 * 线程 C 将调用 odd()，它只输出奇数。
 * <p>
 * 每个线程都有一个 printNumber 方法来输出一个整数。
 * 请修改给出的代码以输出整数序列 010203040506... ，
 * 其中序列的长度必须为 2n。
 */

class ZeroEvenOdd {

    private int n;

    Semaphore even, odd, zero;

    public ZeroEvenOdd(int n) {
        this.n = n;
        zero = new Semaphore(1);
        odd = new Semaphore(0);
        even = new Semaphore(0);
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        boolean printOdd = true;
        for (int i = 0; i < n; i ++) {
            zero.acquire();
            printNumber.accept(0);
            if (printOdd){
                odd.release();
            } else{
                even.release();
            }
            printOdd = ! printOdd;
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        for (int i = 0; i < n / 2; i ++) {
            even.acquire();
            printNumber.accept(i * 2 + 2);
            zero.release();
        }
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        int times = n % 2 == 0 ? n / 2 : n / 2 + 1;
        for (int i = 0; i < times; i ++) {
            odd.acquire();
            printNumber.accept(i * 2 + 1);
            zero.release();
        }
    }


}

